package com.ld.shieldsb.ip2region.core;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.TimeUnit;

import org.lionsoul.ip2region.xdb.Searcher;

import com.ld.shieldsb.common.core.io.IOUtils;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.ip2region.util.IPSearchDBFileLocatorUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Ip2regionSearcher {
    private static String dataPath = "data/ip2region.xdb"; // jar包内外都可以，优先找jar包外的
    private static Searcher searcher = null;

    static {
        File configFile = IPSearchDBFileLocatorUtils.getExtDefaultFile(dataPath); // 判断文件是否存在
        // 如果class目录下不存在
        if (configFile != null && !configFile.exists()) {
            try {
                if (!configFile.getParentFile().exists()) {
                    configFile.getParentFile().mkdirs();
                }
                // 写到class目录下
                IOUtils.readResource2File(IOUtils.readAsInputStream(dataPath), configFile);
            } catch (Exception e) {
                log.error("", e);
            }
        }
        try {
            URL url = IPSearchDBFileLocatorUtils.locate(dataPath);
            // 1、创建 searcher 对象
            // searcher = Searcher.newWithFileOnly(url.getFile());
            // 国家|区域|省份|城市|ISP_
            // 中国|0|山东省|潍坊市|电信

            // 1、从 dbPath 加载整个 xdb 到内存。
            byte[] cBuff = Searcher.loadContentFromFile(url.getFile());

            // 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。
            searcher = Searcher.newWithBuffer(cBuff);

            // 3、查询

            // 4、关闭资源 - 该 searcher 对象可以安全用于并发，等整个服务关闭的时候再关闭 searcher
            // searcher.close();
            // 备注：并发使用，用整个 xdb 数据缓存创建的查询对象可以安全的用于并发，也就是你可以把这个 searcher 对象做成全局对象去跨线程访问。
        } catch (Exception e) {
            log.error("", e);
        }

    }

    /**
     * 查询ip归属地
     * 
     * @Title search
     * @author 吕凯
     * @date 2022年7月23日 上午9:55:59
     * @param ip
     * @return IpInfo
     */
    public static IpInfo search(String ip) {
        IpInfo ipInfo = null;
        try {

            long sTime = System.nanoTime();
            String region = searcher.search(ip);
            long cost = TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() - sTime));
            if (log.isWarnEnabled()) {
                log.warn("region: {}, ioCount: {}, took: {} μs", region, searcher.getIOCount(), cost);
            } else {
                System.out.printf("{region: %s, ioCount: %d, took: %d μs}%n", region, searcher.getIOCount(), cost);
            }

            if (StringUtils.isNotEmpty(region)) {
                ipInfo = new IpInfo();
                if (region != null) {
                    String[] regions = region.split("\\|");
                    String country = regions[0];
                    if (!"0".equals(country)) {
                        ipInfo.setCountry(country);
                    }
                    String province = regions[2];
                    if (!"0".equals(province)) {
                        ipInfo.setProvince(province);
                    }
                    String city = regions[3];
                    if (!"0".equals(city)) {
                        ipInfo.setCity(city);
                    }
                    String isp = regions[4];
                    if (!"0".equals(isp)) {
                        ipInfo.setIsp(isp);
                    }
                    ipInfo.setRegion(region);
                }

            }
        } catch (Exception e) {
            log.error("", e);
        }

        return ipInfo;
    }

    /**
     * 
     * 关闭资源
     * 
     * @Title close
     * @author 吕凯
     * @date 2022年7月23日 上午10:19:58
     * @throws IOException
     *             void
     */
    public static void close() throws IOException {
        if (searcher != null) {
            searcher.close();
        }

    }
}
